<?php
/**
 * Service_Database
 * @author sayp
 * Класс Service_Database отвечает за работу базы данных
 */
class Service_Database {
	
	private static $objDatabase = null; // Экземпляр этого класса
	private $connect; // Дескриптор соединения с БД
	
	/**
	 * Конструктор осуществляет подключение к БД. Запрещаем доступ к нему извне, изменив область видимости
	 */
	private function __construct() {
		$this->connect = mysql_connect(DB_HOST . ':' . DB_PORT, DB_USER, DB_PASS) or die(mysql_error());
		mysql_select_db(DB_NAME, $this->connect) or die(mysql_error());
		mysql_query("SET NAMES utf8");
	}
	
	/**
	 * Запрещаем клонирование объекта
	 */
	private function __clone() {}
	
	/**
	 * Данный метод работает по шаблону синглтон и отдает только один и тот же экземпляр класса
	 * @return Service_Database - экземпляр класса
	 */
	public static function instanse() {
		if (empty(self::$objDatabase)) self::$objDatabase = new Service_Database();
		return self::$objDatabase;
	}
	
	/**
	 * Метод выполняет select запрос
	 * @param string $stmt - sql запрос
	 * @return array $arrResult - двумерный массив
	 */
	public function select($stmt) {
		$result = mysql_query($stmt) or die(mysql_error());
		$arrResult = array();
		while ($row = mysql_fetch_assoc($result))
			$arrResult[] = $row;
		return $arrResult;
	}
	
	/**
	 * Метод выполняет select запрос, когда необходимо получить информацию только об одном столбце
	 * @param string $stmt - sql запрос
	 * @return array $arrResult - одномерный массив
	 */
	public function selectOneColumn($stmt) {
		$result = mysql_query($stmt) or die(mysql_error());
		$arrResult = array();
		while ($row = mysql_fetch_row($result)) $arrResult[] = $row[0];
		return $arrResult;
	}
	
	/**
	 * Метод выполняет select запрос, когда необходимо получить информацию только об одной строке
	 * @param string $stmt - sql запрос
	 * @return array $arrResult - одномерный массив
	 */
	public function selectOneRow($stmt) {
		$result = mysql_query($stmt) or die(mysql_error());
		$arrResult = array();
		if ($row = mysql_fetch_assoc($result)) $arrResult = $row;
		return $arrResult;
	}
	
	/**
	 * Метод выполняет select запрос, когда необходимо только одно значение
	 * @param string $stmt - sql запрос
	 * @return string $return - полученное значение
	 */
	public function selectOneValue($stmt) {
		$result = mysql_query($stmt) or die(mysql_error());
		$return = null;
		if ($row = mysql_fetch_row($result)) $return = $row[0];
		return $return;
	}
	
	/**
	 * Метод выполняет insert запрос
	 * @param string $table - название таблицы
	 * @param array $arrFields - массив, чьи ключи - названия столбцов, а значения - значение столбца
	 */
	public function insert($table, $arrFields, $ignore = false) {
		$fields = '';
		$values = '';
		foreach ($arrFields as $field => $value) {
			if ($fields) {
				$fields .= ',';
				$values .= ',';
			}
			$fields .= "`" . $field . "`";
			// Добавил || $value == '' - понадобилось при добавлении игр, если не указать счёт ставилось 0
			if ($value === null || $value === '') $values .= 'null';
			else $values .= is_numeric($value) ? $value : "'" . $value . "'";
		}
		$stmt = "INSERT " . ($ignore ? "IGNORE " : '') . "INTO `" . $table . "` (" . $fields . ") VALUES (" . $values . ")";
		$result = mysql_query($stmt) or die(mysql_error());
		return($result);
	}
	
	/**
	 * Метод выполняет update запрос
	 * @param string $table - название таблицы
	 * @param array $arrFields - массив, чьи ключи - названия столбцов, а значения - значение столбца
	 * @param string $condition - условие запроса 
	 */
	public function update($table, $arrFields, $condition) {
		//print_r($arrFields);
		$set = '';
		$values = '';
		foreach ($arrFields as $field => $value) {
			// Добавил || $value == '' - понадобилось при обнулении любимого игрока, т.к. иначе присваивался 0 вместо null
			if ($value === null || $value === '') $value = 'null';
			else $value = is_numeric($value) ? $value : "'" . $value . "'";
			if ($set) $set .= ',';
			$set .= '`' . $field . '` = ' . $value; 
		}
		$stmt = "UPDATE `" . $table . "` SET " . $set . ($condition ? ' WHERE ' . $condition : null);
		mysql_query($stmt);
		$result = mysql_affected_rows($this->connect);
		return $result;
	}
	
	/**
	 * Метод выполняет произвольный запрос
	 * @param string $stmt - select запрос
	 */
	public function query($stmt) {
		mysql_query($stmt);
		$result = @mysql_affected_rows($this->connect);
		return $result;
	}
	
	/**
	 * Метод возращает количество найденных строк. Удобно использовать метод для проверки существования запроса
	 * @param strint $stmt - запрос
	 */
	public function numRows($stmt) {
		$result = mysql_query($stmt) or die(mysql_error());
		return mysql_num_rows($result);
	}
	
	/**
	 * Вставляет в определенную таблицу массив значений
	 *
	 * @param string $table - название таблицы
	 * @param array $arFieldValues - массив вставляемых значений (ключ соответствует полю в БД)
	 * @return integer - идентификатор вставленого элемента
	 */
	public function insertAutoincrement($table, $arFieldValues) {
		if ( $this->insert($table, $arFieldValues) ) return $this->getLastInsertId();
		else return false;
	}
	
	/**
	 * Получает информацию о последнем вставленном идентификаторе
	 *
	 * @return integer - значение последнего вставленно идентификатора (false, если не было удачного запроса; 0 если в таблице нет autoincrement)
	 */
	public function getLastInsertId() {
		$stmt = "SELECT LAST_INSERT_ID() AS LID";
		$hRes = mysql_query($stmt, $this->connect);
		if (! $hRes) {//Проверяем, корректно ливыполнен запрос
			$err = mysql_error($this->connect) . $stmt;
			throw new Exception($err);
		}
		$arrLID = mysql_fetch_assoc($hRes);
		return $arrLID['LID'];
	}
	
	/**
	 * Удаляет из таблицы все элементы, удовлетворяющие условию
	 *
	 * @param string $table - название таблицы
	 * @param array $arConditions - массив условий (ключ соответствует полю в БД)
	 * @return integer - количество удаленных строк
	 */
	public function delete($table, $arConditions) {
		//Создаем строку WHERE
		$arWhere = array();//Массив элементов для WHERE
		foreach($arConditions as $field => $val) {  //Проходим массив значений поэлементно
			if ($val === null) {
				$arWhere[] = $field . " IS NULL" ;//Записываем корректное значение в массив
			}
			else {
				//if (! is_numeric($val)) {  //Если текущее значение - не число
				//$val = "'" . absolutelyEscapeString($val) . "'";//Приводим к корректному выводу
				$val = "'" . $val . "'";//Приводим к корректному выводу
				//}
				$arWhere[] = $field . " = " . $val;//Записываем корректное значение в массив
			}
		}
		//Формируем запрос на удаление
		$stmt = "DELETE FROM " . $table . " WHERE " . join(' AND ', $arWhere);
		$hRes = @mysql_query($stmt, $this->connect) or die ("Impossible to request removal" . $stmt . $this->connect);
		if (!$hRes) $this->_checkErrors($stmt); //Проверяем, корректно ливыполнен запрос
		$result = mysql_affected_rows($this->connect);
		return $result;
	}
}

?>